/* main.c */

#include "app_inc.h"

static void LowPower_EnterVlls3(void);

int main(void)
{   
    /* Initialize the board. */
    BSP_InitSystem();
    BSP_InitStdioUART(115200);
    
    printf("\r\n\r\nHello, World\r\n");
    printf("Compiled at %s on %s\r\n", __TIME__, __DATE__);
    
    printf("Press any key to continue ...\r\n");
    getchar();
    
    /* Configure the Button. */
    /* PTA4/LLWU_P3, using as LLWU wake up source. */
    PORTA->PCR[4] =   PORT_PCR_PE_MASK
                    | PORT_PCR_PS_MASK
                    | PORT_PCR_MUX(1); /* GPIO/LLWU. */

    /* Configure the SMC to allow entering into VLLS modes. */
    /* Set the VLLS can be entered. */
    SMC->PMPROT = SMC_PMPROT_AVLLS_MASK; /* Enable VLLS modes. */
    
    /* Configure LLWU as wake up source. */
    LLWU->F1 = 0xFF; LLWU->F2 = 0xFF; /* Clear all flags. */
    LLWU->PE1 |= LLWU_PE1_WUPE3(2); /* Set LLWU_P3's falling edge as wake up event. */
    NVIC_EnableIRQ(LLW_IRQn); /* LLWU ISR will clear the flags before reset. */
    
    printf("Ready to fall into VLLS mode. Would be waken as reset.\r\n");

    LowPower_EnterVlls3();
}

static void LowPower_EnterDeepSleep(bool enSleepOnExit)
{
    /* Set the SLEEPDEEP bit to enable deep sleep mode (STOP) */
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
    if (enSleepOnExit)
    {
        SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
    }
    else
    {
        SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
    }
    /* WFI instruction will start entry into STOP mode */
    __ASM("WFI");
}

static void LowPower_EnterVlls3(void)
{
    volatile uint8_t dummy;

    MCG_C6 &= ~MCG_C6_CME0_MASK; //CME=0 disable clock monitor.
    
    dummy = SMC->PMCTRL & ~SMC_PMCTRL_STOPM_MASK;
    dummy |= SMC_PMCTRL_STOPM(0x4);
    SMC->PMCTRL = dummy;
    SMC->VLLSCTRL = SMC_VLLSCTRL_VLLSM(3);
    dummy = SMC->VLLSCTRL; /* dummy read. */
    /* Now execute the stop instruction to go into VLLS3 */
    LowPower_EnterDeepSleep(false);
}

/* ISR for LLWU. */
void LLW_IRQHandler(void)
{
    uint32_t i;
    
    LLWU->F1 = 0xFF; LLWU->F2 = 0xFF; /* Clear flags. */
    
    SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK;
    PORTE->PCR[6] = PORT_PCR_MUX(1);
    GPIO_SetPinDir(PTE, 6U, true);
    
    GPIO_SetPinLogic(PTE, 6U, false);
    for (i = 0U; i < 10000000U; i++)
    {
        __ASM("NOP");
    }
    GPIO_SetPinLogic(PTE, 6U, true);
    for (i = 0U; i < 10000000U; i++)
    {
        __ASM("NOP");
    }
}

void NMI_Handler(void)
{
    uint32_t i;
    
    SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK;
    PORTE->PCR[7] = PORT_PCR_MUX(1);
    GPIO_SetPinDir(PTE, 7U, true);
    
    GPIO_SetPinLogic(PTE, 7U, false);
    for (i = 0U; i < 1000000U; i++)
    {
        __ASM("NOP");
    }
    GPIO_SetPinLogic(PTE, 7U, true);
    for (i = 0U; i < 1000000U; i++)
    {
        __ASM("NOP");
    }
}

/* EOF. */

